package twitter;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Hashtable;
import java.util.Vector;


public class TwitterServer {
	Connection myConnection;
	Statement statement = null;
    ResultSet rs = null;  
    ServerView view;
    
	String dbAddress = "localhost";
	String dbUserName = "root";
	String dbPassword = "dbpro";
	int port = 5698;
	ClientHandler clientHandler;
	ServerSocket server;
	static int threadNum = 0;
	static int numUpdatedUser = 0;
	static Vector<ClientHandler> cHandlersList = new Vector<ClientHandler>();
    static Hashtable<Integer, Integer> userTable = new Hashtable<Integer, Integer>();

	public TwitterServer(ServerView view) {
		this.view = view;
	}
	/**
	 * handle the requests of the clients
	 * makes a new Thread if the list of threads is empty
	 */
	public void handleConnection() {
		while (true) {
			try {
				Socket socket = server.accept();
				synchronized (cHandlersList) {
					if(cHandlersList.isEmpty()){
						threadNum++;
						ClientHandler cHandler = new ClientHandler(myConnection, socket, view);
						cHandler.start();
					}else{
						ClientHandler cHandler = cHandlersList.firstElement();
						cHandler.setSocket(socket);
						cHandlersList.remove(cHandler);
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	/**
	 * build a connection with the DB
	 * @return Connection
	 */
	public Connection getConnection() {
		Connection con = null;
		try {
			Class.forName("com.mysql.jdbc.Driver").newInstance();
			con = DriverManager.getConnection(
					"jdbc:mysql://" + dbAddress + "/twitterdb", dbUserName, dbPassword);
		} catch (Exception e) {
			view.infoLabel.setText(e.getMessage());
			System.err.println("Exception : " + e.getMessage());
		}
		return con;
	}
	/**
	 * set the updating status of the user table to 0 when starting the server.
	 */
	public void setUserUpdatingStatus(){
		try {
			statement = myConnection.createStatement();
			rs = statement.executeQuery("SELECT id FROM user WHERE updating = 1");
			
			Vector<String> ids = new Vector<String>();
			while(rs.next()){
				ids.add(rs.getString(1));
			}
			for(String id:ids){
				statement.executeUpdate("UPDATE user SET updating = 0 WHERE id =" + id );
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	/**
	 * building the hashtable of the userIds
	 */
	public void BuildUserTable(){
		try {
			statement = myConnection.createStatement();
			rs = statement.executeQuery("SELECT id FROM user");
			while(rs.next()){
				int id = rs.getInt(1);
				userTable.put(id, id);
			}
			view.infoLabel.setText(userTable.size() + " Id's were loaded.");
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	/**
	 * start the server and make the connection with the DB
	 * @return true if successful
	 */
	public boolean connect(){
		try {
			view.infoLabel.setText("loading data...");
			myConnection = getConnection();
			if(myConnection == null){
				return false;
			}
			view.infoLabel.setText("setting user updating status...");
			setUserUpdatingStatus();
			view.infoLabel.setText("building user table...");
			this.BuildUserTable();
			server = new ServerSocket(port);
			view.isOn = true;
			view.infoLabel.setText("Server is ready...");
			this.handleConnection();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return false;
	}
	
}
